<?
/**
 * This file is part of XNAT light.
 *
 * XNAT light is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * XNAT light is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XNAT light.  If not, see <http://www.gnu.org/licenses/>.
 */
namespace NRG\Framework\Common;

use NRG\Framework\Exceptions\IllegalArgumentException as IllegalArgumentException;

/**
 * Abstract Session object
 *
 * @package NRG\Framework\Common
 */
abstract class AbstractSession implements \ArrayAccess, \IteratorAggregate
{
    /**
     * HTTP session reference
     *
     * @var array
     */
    protected $_session;

    /**
     * POST super-global reference
     * 
     * @var array
     */
    protected $_post;
    
    /**
     * GET super-global reference
     *
     * @var array
     */
    protected $_get;

    /**
     * REQUEST super-global reference
     *
     * @var array
     */
    protected $_request;

    /**
     * FILES super-global reference
     * 
     * @var array
     */
    protected $_files;
    
    /**
     * Client URL
     *
     * @var string
     */
    protected $_url;

    /**
     * Request method
     *
     * @var string
     */
    protected $_method;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->_get = &$_GET;
        $this->_post = &$_POST;
        $this->_request = &$_REQUEST;
        $this->_files = &$_FILES;
        $this->_method = strtolower($_SERVER["REQUEST_METHOD"]);
        $this->_session = array();

        $this->populateSession();
    }

    /**
     * Populate HTTP session property
     */
    protected abstract function populateSession();

    /**
     * Retrieve a session parameter
     *
     * @param string $key
     * @param boolean $encode
     * @return mixed
     */
    public function getSessionParam($key, $encode=true)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	if($this->hasSessionParam($key))
	{
	    if($encode)
		return htmlspecialchars($this->_session[$key]);
	    else
		return $this->_session[$key];
	}
	else
	    return null;
    }

    /**
     * Check if session parameter exists
     *
     * @param string $key
     * @return boolean
     */
    public function hasSessionParam($key)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	return isset($this->_session[$key]);

	return false;
    }

    /**
     * Check if a request parameter exists
     *
     * @param string $key
     * @return mixed
     */
    public function hasRequestParam($key)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	return isset($this->_request[$key]);

	return false;
    }

    /**
     * Retrieve a HTTP request parameter
     *
     * @param string $key
     * @return mixed
     */
    public function getRequestParam($key)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	if(isset($this->_request[$key]))
	{
	    if($encode)
		return htmlspecialchars($this->_request[$key]);
	    else
	    	return $this->_request[$key];
	}
	else
	    return null;
    }

    /**
     * Retrieve a POST parameter
     *
     * @param string $key
     * @return mixed
     */
    public function getPostParam($key, $encode=true)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	if(isset($this->_post[$key]))
	{
	    if($encode)
		return htmlspecialchars($this->_post[$key]);
	    else
	    	return $this->_post[$key];
	}
	else
	    return null;
    }

    /**
     * Check if POST parameter exists
     *
     * @param string $key
     * @return boolean
     */
    public function hasPostParam($key)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	return array_key_exists($key, $this->_post);
    }

    /**
     * Retrieve a query parameter by ID
     *
     * @param string $key
     * @return mixed
     */
    public function getQueryParam($key, $encode=true)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	if(isset($this->_get[$key]))
	{
	    if($encode)
		return htmlspecialchars($this->_get[$key]);
	    else
		return $this->_get[$key];
	}
	else
	    return null;
    }

    /**
     * Check if query parameter exists
     *
     * @param string $key
     * @return boolean
     */
    public function hasQueryParam($key)
    {
	if(!is_string($key))
	    throw new IllegalArgumentException("Key must be an instance of string");

	$key = trim($key);

	if($key == "")
	    throw new IllegalArgumentException("Key cannot be empty");

	return array_key_exists($key, $this->_get);
    }

    /**
     * Get all POST parameters
     *
     * @return array
     */
    public function getPostParams($encode=true)
    {
	if($encode)
	{
	    $params = array();

	    foreach($this->_post as $key => $value)
		$params[$key] = htmlspecialchars($value);

	    return $params;
	}
	else
	    return $this->_post;
    }

    /**
     * Get all query parameters
     *
     * @return array
     */
    public function getQueryParams($encode=true)
    {
	if($encode)
	{
	    $params = array();

	    foreach($this->_get as $key => $value)
		$params[$key] = htmlspecialchars($value);

	    return $params;
	}
	else
	    return $this->_get;
    }

    /**
     * Get request method
     *
     * @return string
     */
    public function getMethod()
    {
        return $this->_method;
    }
    
    /**
     * Allows class to be used as an array
     *
     * ArrayAccess::offsetSet implementation
     *
     * @param mixed $offset
     * @param mixed $value 
     */
    public function offsetSet($offset, $value)
    {
	if(is_null($offset))
	{
            $this->_session[] = $value;
        }
	else
	{
            $this->_session[$offset] = $value;
        }
    }

    /**
     * Allows class to be used as an array
     *
     * ArrayAccess::offsetExists implementation
     *
     * @param mixed $offset
     * @return boolean
     */
    public function offsetExists($offset)
    {
        return isset($this->_session[$offset]);
    }

    /**
     * Allows class to be used as an array
     *
     * ArrayAccess::offsetUnset implementation
     *
     * @param mixed $offset
     */
    public function offsetUnset($offset)
    {
        unset($this->_session[$offset]);
    }

    /**
     * Allows class to be used as an array
     *
     * ArrayAccess::offsetGet implementation
     *
     * @param mixed $offset
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return isset($this->_session[$offset]) ? $this->_session[$offset] : null;
    }

    /**
     * Allows class to be iterated over
     *
     * IteratorAggregate::getIterator implementation
     */
    public function getIterator()
    {
	    return new \ArrayIterator($this->_session);
    }

    /**
     * Get file by filename
     */
    public function getFileByName($name)
    {
        foreach($this->_files as $file)
        {
            if($file["name"] == $name)
            {
                return $file["tmp_name"];
            }
        }

        return null;
    }

    public function getFileByKey($key)
    {
        if(array_key_exists($key, $this->_files))
            return $this->_files[$key]["tmp_name"];
        
        return null;
    }
}
